# 第04章 Jackson

# 1.1 Jackson简介

Jackson是一种JSON API,也是最流行,速度最快的JSON API。Jackson的在线API文档可以在http://wiki.fasterxml.com/JacksonInFiveMinutes中找到。Jackson的源代码托管在:https://github.com/FasterXML/jackson。 Jackson提供了两种不同的JSON解析器:

  • ObjectMapper:把JSON解析到自定义的Java类中,或者解析到一个Jackson指定的树形结构中(Tree model)。
  • Jackson JsonParser:一种“拉式”(pull)解析器,每次解析一组JSON数据。

Jackson也包含了两种不同的JSON生成器:

  • ObjectMapper:把自定义的Java类,或者一个Jackson指定的树形结构生成为JSON文件。
  • Jackson JsonGenerator:每次只生成一组JSON数据。

# 1.2 Jackson依赖

Jackson包含一个core JAR,和两个依赖core JAR的JAR:

  • ​ Jackson Core
  • ​ Jackson Annotations
  • ​ Jackson Databind

其中Jackson Annotations依赖Jackson Core,Jackson Databind依赖Jackson Annotations。

gradle

// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.5'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.5'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5'
1
2
3
4
5
6

maven

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.5</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.5</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 1.3 简单使用

# 1.3.1 User

//JSON序列化和反序列化使用的User类  
import java.util.Date;  

public class User {  
    private String name;  
    private Integer age;  
    private Date birthday;  
    private String email;  
    // getter & setter
}
1
2
3
4
5
6
7
8
9
10

# 1.3.2 Java对象转JSON

import java.io.IOException;  
import java.text.ParseException;  
import java.text.SimpleDateFormat;  

import com.fasterxml.jackson.databind.ObjectMapper;  

public class JacksonDemo {  
    public static void main(String[] args) throws ParseException, IOException {  
        User user = new User();  
        user.setName("小民");   
        user.setEmail("xiaomin@sina.com");  
        user.setAge(20);  

        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");  
        user.setBirthday(dateformat.parse("1996-10-01"));         

/** 
* ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。 
* ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。 
* writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。 
* writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。 
* writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。 
* writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。 
*/  
        ObjectMapper mapper = new ObjectMapper();  

//User类转JSON  
//输出结果:{"name":"小民","age":20,"birthday":844099200000,"email":"xiaomin@sina.com"} 
        String json = mapper.writeValueAsString(user);  
        System.out.println(json);  

//Java集合转JSON  
//输出结果:[{"name":"小民","age":20,"birthday":844099200000,"email":"xiaomin@sina.com"}]  
        List<User> users = new ArrayList<User>();  
        users.add(user);  
        String jsonlist = mapper.writeValueAsString(users);  
        System.out.println(jsonlist);  
    }  
}  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 1.3.3 Json转Java对象

import java.io.IOException;  
import java.text.ParseException;  
import com.fasterxml.jackson.databind.ObjectMapper;  

public class JacksonDemo {  
    public static void main(String[] args) throws ParseException, IOException {  
        String json = "{\"name\":\"小民\",\"age\":20,\"birthday\":844099200000,\"email\":\"xiaomin@sina.com\"}";  

/** 
* ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。 
*/  
        ObjectMapper mapper = new ObjectMapper();  
        User user = mapper.readValue(json, User.class);  
        System.out.println(user);  
    }  
}  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 1.3.4 Json注解

Jackson提供了一系列注解,方便对JSON序列化和反序列化进行控制,下面介绍一些常用的注解。

  • @JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。
  • @JsonFormat 此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。
  • @JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty("name")。
import java.util.Date;  
import com.fasterxml.jackson.annotation.*;  
  
public class User {  
    private String name;  
      
    //不JSON序列化年龄属性  
    @JsonIgnore   
    private Integer age;  
      
    //格式化日期属性  
    @JsonFormat(pattern = "yyyy年MM月dd日")  
    private Date birthday;  
      
    //序列化email属性为mail  
    @JsonProperty("mail")  
    private String email;  
      
    // getter & setter
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

示例:

import java.io.IOException;  
import java.text.ParseException;  
import java.text.SimpleDateFormat;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
public class JacksonDemo {  
  
    public static void main(String[] args) throws ParseException, IOException {  
        User user = new User();  
        user.setName("小民");   
        user.setEmail("xiaomin@sina.com");  
        user.setAge(20);  
          
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");  
        user.setBirthday(dateformat.parse("1996-10-01"));         
          
        ObjectMapper mapper = new ObjectMapper();  
        String json = mapper.writeValueAsString(user);  
        System.out.println(json);  
//输出结果:{"name":"小民","birthday":"1996年09月30日","mail":"xiaomin@sina.com"}  
    }  
} 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 1.4 ObjectMapper

# 1.4.1 ObjectMapper解析JSON

# 解析String

public static void readFromString(){  
    String carJson =  "{ \"brand\" : \"Mercedes\"," +  
        "  \"doors\" : 5," +  
        "  \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +  
        "  \"nestedObject\" : { \"field\" : \"value\" } }";  

    ObjectMapper objectMapper = new ObjectMapper();  

    try {  
        //Read JSON from a Reader instance.  
        //Reader reader = new StringReader(carJson);  
        //JsonNode node = objectMapper.readValue(reader, JsonNode.class);  
        JsonNode node = objectMapper.readValue(carJson, JsonNode.class);  

        JsonNode brandNode = node.get("brand");  
        String brand = brandNode.asText();  
        System.out.println("brand = " + brand);  

        JsonNode doorsNode = node.get("doors");  
        Integer doors = doorsNode.asInt();  
        System.out.println("doors = " + doors);  

        JsonNode owners = node.get("owners");  
        JsonNode johnNode = owners.get(0);  
        String owner = johnNode.asText();  
        System.out.println("john = " + owner);  

        JsonNode nestNode = node.get("nestedObject");  
        JsonNode fieldNode = nestNode.get("field");  
        String field = fieldNode.asText();  
        System.out.println("field = " + field);  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 解析对象POJO

ObjectMapper如果解析JSON到Java类,那么这个Java类必须是简单的POJO,这个POJO的User的代码就不贴了:

public static void readToPOJO()throws IOException{  
    String json = "{ \"name\": \"Gatsby\","  
        + "  \"gender\": \"MALE\","  
        + "  \"age\": 24"  
        + "}";  
    ObjectMapper objectMapper = new ObjectMapper();  

    try{  
        User user = objectMapper.readValue(json, User.class);  
        System.out.print(user.toString());  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 解析文件

Car.json

{  
    "brand": "Mercedes",  
    "doors": 5,  
    "owner": {  
        "first": "Gatsby",  
        "last": "Newton"  
    },  
    "component": ["engine", "brake"]  
} 
1
2
3
4
5
6
7
8
9

解析:

public static void readFromFile(){  
    try {  
        String path = "F:\\Codes\\IDEA\\Tools\\data\\json\\car.json";  
        // Read JSON from an local file.  
        // File file = new File(path);  
        // Read JSON from an InputStream.  
        InputStream input = new FileInputStream(path);  
        ObjectMapper objectMapper = new ObjectMapper();  
        JsonNode node = objectMapper.readValue(input, JsonNode.class);  

        JsonNode brandNode = node.get("brand");  
        String brand = brandNode.asText();  
        System.out.println("brand = " + brand);  

        JsonNode doorsNode = node.get("doors");  
        Integer doors = doorsNode.asInt();  
        System.out.println("doors = " + doors);  

        JsonNode ownerNode = node.get("owner");  
        JsonNode nameNode = ownerNode.get("first");  
        String first = nameNode.asText();  
        System.out.println("first = " + first);  

        JsonNode comsNode = node.get("component");  
        JsonNode comNode = comsNode.get(0);  
        String component = comNode.asText();  
        System.out.println("component = " + component);  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 1.4.2 ObjectMapper生成JSON

和解析JSON一样,ObjectMapper也可以把JSON生成到String,自定义的Java类,File中

生成String

public static void writeToString(){  
    Car car = new Car("BMW", 4, new Car.Owner("Gatsby", "Newton"), new String[]{"engine", "brake"});  
  
    ObjectMapper objectMapper = new ObjectMapper();  
  
    try{  
        String json = objectMapper.writeValueAsString(car);  
        System.out.println(json);  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
} 
1
2
3
4
5
6
7
8
9
10
11
12
13

生成到文件中

public static void writeToFile()throws IOException{  
    Car car = new Car("BMW", 4, new Car.Owner("Gatsby", "Newton"), new String[]{"engine", "brake"});  

    ObjectMapper objectMapper = new ObjectMapper();  
    OutputStream outputStream = null;  

    try{  
        outputStream = new FileOutputStream(new File("F:\\Codes\\IDEA\\Tools\\data\\json\\out\\out.json"));  
        objectMapper.writeValue(outputStream, car);  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
    finally {  
        if (outputStream != null){  
            outputStream.close();  
        }  
    }  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 1.5 JsonParser

Jackson JsonParser比Jackson ObjectMapper更底层,这就使得Jackson JsonParser比ObjectMapper更快,但是也更加笨重。Jackson JsonParser的工作方式是:将JSON分成一个记号序列,让你迭代记号(Token)序列进行解析。Jackson Parser的Token有:

  • ​ START_OBJECT
  • ​ END_OBJECT
  • ​ START_ARRAY
  • ​ END_ARRAY
  • ​ FIELD_NAME
  • ​ VALUE_EMBEDDED_OBJECT
  • ​ VALUE_FALSE
  • ​ VALUE_TRUE
  • ​ VALUE_NULL
  • ​ VALUE_STRING
  • ​ VALUE_NUMBER_INT
  • ​ VALUE_NUMBER_FLOAT

这些Token在JsonToken类中,通过nextToken()获取。 getCurrentName()获取当前Field Name,而Value可以用getText()获取,也可以用getValueAsString()、getValueAsInt()等类似的方法获取。 同Jackson ObjectMapper一样,你也可以解析String、Reader、InputStream、URL、byte数组、char数组

User.json

{  
    "name": {  
        "first": "Joe",  
        "last": "Sixpack"  
    },  
    "gender": "MALE",  
    "verified": false,  
    "userImage": "Rm9vYm"  
}  
1
2
3
4
5
6
7
8
9

示例:

public static void readFromFile(){  
    String path = "F:\\Codes\\IDEA\\Tools\\data\\json\\user.json";  
    //String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";  
    JsonFactory jsonFactory = new JsonFactory();  
    User user = new User();  

    try {  
        JsonParser parser = jsonFactory.createParser(new File(path));  
        parser.nextToken();    //进入JSON的“{”  
        while (parser.nextToken() != JsonToken.END_OBJECT){  
            String fieldName = parser.getCurrentName();  
            parser.nextToken();  
            if(fieldName.equals("name")) {  
                System.out.println(fieldName + ":");  
                while (parser.nextToken() != JsonToken.END_OBJECT) {  
                    parser.nextToken();  
                    String field = parser.getCurrentName();  
                    System.out.println("\t" + field + ": " + parser.getValueAsString());  
                }  
            }  
            else {  
                System.out.println(fieldName + ": " + parser.getText());  
            }  
        }  
        parser.close();  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 1.6 Generator

Jackson Generator用于生成JSON。

对于简单的变量这种数据类型,Jackson Generator和Jackson JsonParser一样从JsonFactory中创建。

示例代码:

// Write simple variables to file  
public static void writeSimpleToFile(){  

    JsonFactory jsonFactory = new JsonFactory();  
    OutputStream outputStream = null;  
    //Car car = new Car("BMW", 4, new Car.Owner("Gatsby", "Newton"), new String[]{"engine", "brake"});  

    try {  
        outputStream = new FileOutputStream("F:\\Codes\\IDEA\\Tools\\data\\json\\out\\generate_simple.json");  
        JsonGenerator generator = jsonFactory.createGenerator(outputStream, JsonEncoding.UTF8);  
        generator.writeStartObject();  

        generator.writeStringField("brand", "Mercedes");  
        generator.writeNumberField("doors", 5);  
        generator.writeObjectFieldStart("owner");  
        generator.writeStringField("first", "Gatsby");  
        generator.writeStringField("last", "Newton");  
        generator.writeEndObject();  

        generator.writeArrayFieldStart("component");  
        generator.writeString("engine");  
        generator.writeString("brake");  
        generator.writeEndArray();  

        // Write a object.  
        // generator.writeObjectField("owner", new Car.Owner("Gatsby", "Newton"));  
        // generator.writeObjectField("component", new String[]{"engine", "brake"}); 
        generator.writeEndObject();  

        generator.flush();  
        generator.close();  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

输入的文件内容:

{"brand":"Mercedes","doors":5,"owner":{"first":"Gatsby","last":"Newton"},"component":["engine","brake"]}
1

复杂数据类型

Jackson Generator必须从ObjectMapper.getJsonFactory()的JsonFactory中创建,否则会报一下错误: java.lang.IllegalStateException: No ObjectCodec defined for the generator,can only serialize simple wrapper types (type passed edu.wzm.jackson.Car$Owner)
其中,ObjectMapper.getJsonFactory()方法被标记为deprecated,不过这并没有关系,这种情况在Java编程中经常遇到,这是可以用的。但是对于那种建议不要使用的方法,最好弃之不用。

// Write objects to file.  
public static void writeComplexToFile(){  

    // If you use JsonFactory jsonFactory = new JsonFactory(), it shows the error:  
    // java.lang.IllegalStateException: No ObjectCodec defined for the generator,  
    // can only serialize simple wrapper types (type passed edu.wzm.jackson.Car$Owner)  
    JsonFactory jsonFactory = new ObjectMapper().getJsonFactory();  

    OutputStream outputStream = null;  
    // Car car = new Car("BMW", 4, new Car.Owner("Gatsby", "Newton"), new String[]{"engine", "brake"});  

    try {  
        outputStream = new FileOutputStream("F:\\Codes\\IDEA\\Tools\\data\\json\\out\\generate_complex.json");  
        JsonGenerator generator = jsonFactory.createGenerator(outputStream, JsonEncoding.UTF8);  
        generator.writeStartObject();  

        generator.writeStringField("brand", "Mercedes");  
        generator.writeNumberField("doors", 5);  

        // Write a object.  
        generator.writeObjectField("owner", new Car.Owner("Gatsby", "Newton"));  
        generator.writeObjectField("component", new String[]{"engine", "brake"});  

        generator.writeEndObject();  

        generator.flush();  
        generator.close();  
    }  
    catch (Exception e){  
        e.printStackTrace();  
    }  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

结果:

{"brand":"Mercedes","doors":5,"owner":{"first":"Gatsby","last":"Newton"},"component":["engine","brake"]}

Last Updated: 10/20/2019, 11:49:45 PM